package com.xiaoshuidi.cloud.module.rooms.repository;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.mybatis.core.dataobject.BaseDO;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.reservation.vo.GetByUserIdRespVO;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.reservation.vo.ReserveBillPageReq;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.reservation.vo.ReserveBillPageResp;
import com.xiaoshuidi.cloud.module.rooms.enums.RoomHouseReservePaymentStatus;
import com.xiaoshuidi.cloud.module.rooms.enums.RoomHouseReserveStatus;
import com.xiaoshuidi.cloud.module.rooms.mapper.RoomHouseReserveMapper;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomHouseReserve;
import org.springframework.stereotype.Repository;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * @Author Feng
 * @date 2023/5/15
 */
@Repository
public class RoomHouseReserveRepository extends ServiceImpl<RoomHouseReserveMapper, RoomHouseReserve> {

    /**
     * 查询支付期限小于当前日期的预定单
     *
     * @param depositPaymentTerm
     * @return
     */
    public List<RoomHouseReserve> toBePayList(LocalDate depositPaymentTerm) {
        LambdaQueryWrapper<RoomHouseReserve> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(RoomHouseReserve::getStatus, RoomHouseReserveStatus.TO_BE_PAID.getCode())
                .lt(RoomHouseReserve::getDepositPaymentTerm, depositPaymentTerm);
        return list(wrapper);
    }

    public List<RoomHouseReserve> toBePay() {
        LambdaQueryWrapper<RoomHouseReserve> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(RoomHouseReserve::getStatus, RoomHouseReserveStatus.TO_BE_PAID.getCode());
        wrapper.ge(RoomHouseReserve::getDepositPaymentTerm, LocalDateTime.now());
        return list(wrapper);
    }

    /**
     * 查询已预定过期的预定单
     *
     * @param expirationDate
     * @return
     */
    public List<RoomHouseReserve> reservedList(LocalDate expirationDate) {
        LambdaQueryWrapper<RoomHouseReserve> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(RoomHouseReserve::getStatus, RoomHouseReserveStatus.RESERVED.getCode())
                .lt(RoomHouseReserve::getExpirationDate, expirationDate);
        return list(wrapper);
    }

    public List<RoomHouseReserve> reserved() {
        LambdaQueryWrapper<RoomHouseReserve> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(RoomHouseReserve::getStatus, RoomHouseReserveStatus.RESERVED.getCode());
        wrapper.gt(RoomHouseReserve::getExpirationDate, LocalDateTime.now());
        return list(wrapper);
    }

    /**
     * 根据房源信息获取最新一条待支付、已预订状态的预定单
     *
     * @param roomHouseId
     * @return
     */
    public RoomHouseReserve getByRoomHouseId(Long roomHouseId) {
        LambdaQueryWrapper<RoomHouseReserve> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(RoomHouseReserve::getRoomHouseId, roomHouseId)
                .in(RoomHouseReserve::getStatus, Arrays.asList(RoomHouseReserveStatus.TO_BE_PAID.getCode(), RoomHouseReserveStatus.RESERVED.getCode()))
                .orderByDesc(BaseDO::getCreateTime)
                .last("limit 1");
        return this.getOne(wrapper);
    }

    /**
     * 根据房源信息查询已签约、已取消的预定单列表
     *
     * @param roomHouseId
     * @param pageNo
     * @param pageSize
     * @return
     */
    public Page<RoomHouseReserve> pageByRoomHouseId(Long roomHouseId, Integer pageNo, Integer pageSize) {
        Page<RoomHouseReserve> page = Page.of(pageNo, pageSize);
        LambdaQueryWrapper<RoomHouseReserve> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(RoomHouseReserve::getRoomHouseId, roomHouseId)
                .in(RoomHouseReserve::getStatus, Arrays.asList(RoomHouseReserveStatus.CANCELED.getCode(), RoomHouseReserveStatus.SINGED.getCode(),
                        RoomHouseReserveStatus.RETIRED.getCode(),RoomHouseReserveStatus.FAILURE.getCode()))
                .orderByDesc(BaseDO::getCreateTime);
        return this.page(page, wrapper);
    }

    /**
     * 预定账单
     *
     * @param req
     * @return
     */
    public Page<ReserveBillPageResp> billPage(ReserveBillPageReq req) {
        Page<ReserveBillPageResp> page = Page.of(req.getPageNo(), req.getPageSize());
        QueryWrapper<ReserveBillPageReq> wrapper = billWrapper(req);
        return this.baseMapper.billPage(page, wrapper);
    }

    /**
     * 根据条件获取总条数 - 预定账单导出使用
     *
     * @param req
     * @return
     */
    public Long billCount(ReserveBillPageReq req) {
        QueryWrapper<ReserveBillPageReq> wrapper = billWrapper(req);
        return this.baseMapper.billCount(wrapper);
    }

    private QueryWrapper<ReserveBillPageReq> billWrapper(ReserveBillPageReq req) {
        QueryWrapper<ReserveBillPageReq> wrapper = Wrappers.query();
        wrapper.eq("rhr.deleted", false)
                .eq("rh.deleted", false)
                .eq(req.getApartmentId() != null, "rh.apartment_id", req.getApartmentId())
                .eq(StrUtil.isNotEmpty(req.getPaymentStatus()), "rhr.payment_status", req.getPaymentStatus())
                .eq(StrUtil.isNotEmpty(req.getStatus()),"rhr.status",req.getStatus())
                .eq(StrUtil.isNotEmpty(req.getCustomType()), "rhr.custom_type", req.getCustomType())
                .and(StrUtil.isNotEmpty(req.getSearch()), s -> s.like("rhr.booker", req.getSearch()).or()
                        .like("rhr.company_name", req.getSearch()).or()
                        .like("rh.name", req.getSearch()).or()
                        .like("rhr.booker_phone",req.getSearch()))
                .ge(StrUtil.isNotEmpty(req.getPaymentDateStart()), "rhr.deposit_payment_term", req.getPaymentDateStart())
                .le(StrUtil.isNotEmpty(req.getPaymentDateEnd()), "rhr.deposit_payment_term", req.getPaymentDateEnd())
                .orderByDesc("rhr.create_time");
        return wrapper;
    }

    public Page<RoomHouseReserve> getMyReserve(Integer pageNum, Integer pageSize, Integer payState, String bookerPhone) {
        LambdaQueryWrapper<RoomHouseReserve> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(RoomHouseReserve::getBookerPhone, bookerPhone);
        if (payState.equals(1)) {
            // 待支付
            wrapper.eq(RoomHouseReserve::getPaymentStatus, RoomHouseReservePaymentStatus.UNTREATED.getCode());
        } else if (payState.equals(2)) {
            // 已支付
            wrapper.eq(RoomHouseReserve::getPaymentStatus, RoomHouseReservePaymentStatus.PROCESSED.getCode());
        }
        return this.baseMapper.selectPage(new Page<>(pageNum, pageSize), wrapper);
    }

    public RoomHouseReserve getByRoomIdAndMemberId(Long roomHouseId, Long memberId, String status) {
        LambdaQueryWrapper<RoomHouseReserve> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(RoomHouseReserve::getRoomHouseId, roomHouseId)
                .eq(RoomHouseReserve::getBookerId, memberId)
                .eq(RoomHouseReserve::getStatus, status)
                .last("limit 1");
        return this.getOne(wrapper);
    }

    public Page<GetByUserIdRespVO> getByBookerId(Long userId, Integer pageNo, Integer pageSize) {
        QueryWrapper<RoomHouseReserve> wrapper = Wrappers.query();
        wrapper.eq("rhr.booker_id", userId);
        wrapper.eq("rhr.deleted", 0);
        wrapper.orderByDesc("rhr.create_time");
        return this.baseMapper.getByBookerId(new Page<RoomHouseReserve>(pageNo, pageSize), wrapper);
    }

    public void updateMember(Long userId, String mobile) {
        this.baseMapper.updateMember(userId,mobile);
    }


    public PageResult<ReserveBillPageResp> withdrawBillPage(ReserveBillPageReq req) {
        Page<ReserveBillPageResp> page = new Page<>(req.getPageNo(),req.getPageSize());
        IPage<ReserveBillPageResp> reserveBillPageRespIPage = this.baseMapper.pageWithdrawBillList(page, req);
        return new PageResult<>(reserveBillPageRespIPage.getRecords(),  reserveBillPageRespIPage.getTotal());
    }
}
